import {MicroAppModule} from "./MicroAppModule";
import {toArray} from "@peryl/react-compose";
import {pathJoin} from "@peryl/utils/pathJoin";
import {GLOBAL_NAME, iMicroApp} from "@peryl/micro-web";

export const microAppResource = MicroAppModule.createRegistration((option) => {
  /**
   * 资源管理器
   * @author  韦胜健
   * @date    2024/1/31 14:18
   */
  const resource: iMicroApp['resource'] = {
    resourceConfigs: [],
    load: async (name: string, Win: any) => {
      if (!Win[GLOBAL_NAME.RESOURCE]) {Win[GLOBAL_NAME.RESOURCE] = {};}
      if (!Win[GLOBAL_NAME.RESOURCE][name]) {
        Win[GLOBAL_NAME.RESOURCE][name] = (async () => {
          const resourceConfig = resource.resourceConfigs.find(i => i.name === name);
          if (!resourceConfig) {throw new Error(`resource: ${name} is not defined!`);}
          if (!!resourceConfig.dependencies) {await Promise.all(resourceConfig.dependencies.map(i => resource.load(i, Win)));}
          const Module = await (async () => {
            if (typeof resourceConfig.loader === "function") {
              return resourceConfig.loader();
            } else {
              const jsList = toArray(resourceConfig.loader.js || []);
              const cssList = toArray(resourceConfig.loader.css || []);
              await Promise.all([
                ...jsList.map(i => resource.loadFile(i + `?v=${resourceConfig.version}`, Win)),
                ...cssList.map(i => resource.loadFile(i + `?v=${resourceConfig.version}`, Win)),
              ]);
              return Win[resourceConfig.globalName || name];
            }
          })();
          if (!Win[name]) {Win[name] = Module;}
          return Module;
        })();
      }
      return Win[GLOBAL_NAME.RESOURCE][name];
    },
    loadFile: async (filePath, Win: any) => {
      if (filePath.indexOf('http') !== 0) {
        filePath = pathJoin(option.baseAssetsPublicPath.get(), filePath);
      }
      if (!Win[GLOBAL_NAME.RES_FILE]) {Win[GLOBAL_NAME.RES_FILE] = {};}
      if (!Win[GLOBAL_NAME.RES_FILE][filePath]) {
        Win[GLOBAL_NAME.RES_FILE][filePath] = new Promise((resolve, reject) => {
          if (/\.js(\?.*)?/.test(filePath)) {
            const el = Win.document.createElement('script') as HTMLScriptElement;
            el.setAttribute('src', filePath);
            el.onload = resolve;
            el.onerror = reject;
            Win.document.body.appendChild(el);
          } else if (/\.css(\?.*)?/.test(filePath)) {
            const el = Win.document.createElement('link') as HTMLLinkElement;
            el.setAttribute('rel', 'stylesheet');
            el.setAttribute('type', 'text/css');
            el.setAttribute('href', filePath);
            el.onload = resolve;
            el.onerror = reject;
            Win.document.body.appendChild(el);
          }
        });
      }
      return Win[GLOBAL_NAME.RES_FILE][filePath];
    },
    registry: (resourceConfig) => {
      resource.resourceConfigs.push(resourceConfig);
    },
  };
  return resource;
});
